package com.hex.ds.hdtp.core.app.data.contrast.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.hex.ds.hdtp.core.app.common.page.PageData;
import com.hex.ds.hdtp.core.app.common.page.converter.IPageAndPageDtoConverter;
import com.hex.ds.hdtp.core.app.common.page.dto.PageDto;
import com.hex.ds.hdtp.core.app.common.util.ExcelDownUtil;
import com.hex.ds.hdtp.core.app.data.contrast.converter.ICrossDbContrastTemplateConverter;
import com.hex.ds.hdtp.core.app.data.contrast.dto.ContrastTemplateExcelDto;
import com.hex.ds.hdtp.core.app.data.contrast.dto.ContrastTemplateImportExcelDto;
import com.hex.ds.hdtp.core.app.data.contrast.dto.request.CrossDbContrastTemplateRequestDto;
import com.hex.ds.hdtp.core.app.data.contrast.dto.response.CrossDbContrastTemplateResponseDto;
import com.hex.ds.hdtp.core.app.data.contrast.service.ICrossDbContrastTemplateService;
import com.hex.ds.hdtp.core.inf.common.page.Page;
import com.hex.ds.hdtp.core.inf.data.contrast.po.CrossDbContrastTemplatePo;
import com.hex.ds.hdtp.core.inf.data.contrast.repository.ICrossDbContrastTemplateRepository;
import liquibase.util.file.FilenameUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.hex.bigdata.hbda.utils.FileUtil.upload;

/**
 * @Package: com.hex.ds.hdtp.core.app.data.contrast.service.impl
 * @ClassName CrossDbContrastTemplateService
 * @Description: 跨库比对模板-业务接口实现
 * @Author: wz.li
 * @Date 2023/7/24 19:20
 * @Version v2.0.2
 **/
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CrossDbContrastTemplateService implements ICrossDbContrastTemplateService {

    private final ICrossDbContrastTemplateRepository crossDbContrastTemplateRepository;

    private final ICrossDbContrastTemplateConverter converter;

    private final IPageAndPageDtoConverter pageAndPageDtoConverter;

    @Value("${file.path}")
    private String filePath;

    /*
     * @Method: queryListByPage <br>
     * @Param: [crossDbContrastTemplateRequestDto, pageDto] <br>
     * @Return: com.hex.ds.hdtp.core.app.common.page.PageData <br>
     * @Description：分页查询<br>
     * @Author： wz.li<br>
     * @Date： 2023/7/24 19:23 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public PageData queryListByPage(CrossDbContrastTemplateRequestDto crossDbContrastTemplateRequestDto, PageDto pageDto) {
        final Page<CrossDbContrastTemplatePo> pageResult = crossDbContrastTemplateRepository.queryListByPage(
                converter.toCrossDbContrastTemplatePo(crossDbContrastTemplateRequestDto), pageAndPageDtoConverter.toPage(pageDto));
        List<CrossDbContrastTemplateResponseDto> responseDtos = converter.toCrossDbContrastTemplateResponseDtoList(pageResult.getData());
        return new PageData(responseDtos, pageResult.getTotal());
    }

    /*
     * @Method: add <br>
     * @Param: [crossDbContrastTemplateRequestDto] <br>
     * @Return: void <br>
     * @Description：新增跨库比对模板<br>
     * @Author： wz.li<br>
     * @Date： 2023/7/24 19:26 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public void add(CrossDbContrastTemplateRequestDto crossDbContrastTemplateRequestDto) {
        int count = crossDbContrastTemplateRepository.add(converter.toCrossDbContrastTemplatePo(crossDbContrastTemplateRequestDto));
        if (count != 1) {
            throw new RuntimeException("新增跨库对比模板失败");
        }
    }

    /*
     * @Method: modifyById <br>
     * @Param: [crossDbContrastTemplateRequestDto] <br>
     * @Return: void <br>
     * @Description：根据主键更新<br>
     * @Author： wz.li<br>
     * @Date： 2023/7/24 19:26 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public void modifyById(CrossDbContrastTemplateRequestDto crossDbContrastTemplateRequestDto) {
        int count = crossDbContrastTemplateRepository.modifyById(converter.toCrossDbContrastTemplatePo(crossDbContrastTemplateRequestDto));
        if (count != 1) {
            throw new RuntimeException("更新跨库对比模板失败");
        }
    }

    /*
     * @Method: removeById <br>
     * @Param: [pkId] <br>
     * @Return: void <br>
     * @Description：根据主键删除<br>
     * @Author： wz.li<br>
     * @Date： 2023/7/24 19:26 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public void removeById(String pkId) {
        int count = crossDbContrastTemplateRepository.removeById(pkId);
        if (count != 1) {
            throw new RuntimeException("删除跨库对比模板失败");
        }
    }

    /*
     * @Method: batchRemoveById <br>
     * @Param: [pkIds] <br>
     * @Return: void <br>
     * @Description：批量删除跨库比对模板<br>
     * @Author： wz.li<br>
     * @Date： 2023/7/24 19:26 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void batchRemoveById(List<String> pkIds) {
        for (String pkId : pkIds) {
            removeById(pkId);
        }
    }

    /*
     * @Method: queryById <br>
     * @Param: [pkId] <br>
     * @Return: com.hex.ds.hdtp.core.app.data.contrast.dto.response.CrossDbContrastTemplateResponseDto <br>
     * @Description：根据主键查询<br>
     * @Author： wz.li<br>
     * @Date： 2023/7/26 13:59 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public CrossDbContrastTemplateResponseDto queryById(String pkId) {
        return converter.toCrossDbContrastTemplateResponseDto(crossDbContrastTemplateRepository.queryById(pkId));
    }
    /*
     * @Method: exportData <br>
     * @Param:
     * @Return: void <br>
     * @Description：导出比对模板<br>
     * @Author：hui.hu<br>
     * @Date： 2023/12/7 19:26 <br>
     * @Version： V2.0.2<br>
     */
    @Override
    public String exportData(List<String> pkIdList) {
        ArrayList<ContrastTemplateExcelDto> contrastTemplateExcelDtos = new ArrayList<>();
        Integer index = 1;
        //获取比对模板
        for (String pkId : pkIdList) {
            ContrastTemplateExcelDto contrastTemplateExcelDto = converter.toContrastTemplateExcelDto(queryById(pkId), index++);
            contrastTemplateExcelDtos.add(contrastTemplateExcelDto);
        }
        String backUpPath = createSavePath();
        String templateFilePath = "static/contrastTemplate.xlsx";
        String saveFilePath = backUpPath + File.separator + "比对任务模板.xlsx";
        ExcelDownUtil.generatedExcel(contrastTemplateExcelDtos, templateFilePath, saveFilePath);
        return saveFilePath;
    }

    @Override
    public Map importExcel(MultipartFile file) {
        Map resultMap = new HashMap();
        try {
            // 1.备份导入的EXCEL文件
            String backUpFilePath = backupUploadFile(file);
            // 2.读取EXCEL文件数据
            List<ContrastTemplateImportExcelDto> excelData = getExcelData(backUpFilePath);
            // 3.校验数据
            if(verifyData(excelData)!=null && !verifyData(excelData).isEmpty()){
                String errorMessage = StrUtil.format("导入失败，请校验模板名称{}（模板名称重复或为空）", verifyData(excelData));
                throw new RuntimeException(errorMessage);
            }
            // 4.保存数据
            updateDbDataByExcel(excelData);
            resultMap.put("status", true);
        } catch (Exception e) {
            resultMap.put("status", false);
            resultMap.put("message", e.getMessage());
        }
        return resultMap;
    }

    @Override
    public CrossDbContrastTemplateResponseDto queryByTemplateName(String templateName) {
        CrossDbContrastTemplatePo crossDbContrastTemplatePo = crossDbContrastTemplateRepository.queryByTemplateName(templateName);
        return converter.toCrossDbContrastTemplateResponseDto(crossDbContrastTemplatePo);
    }

    private void updateDbDataByExcel(List<ContrastTemplateImportExcelDto> excelData) {
        for (ContrastTemplateImportExcelDto importDto : excelData) {
            add(converter.toCrossDbContrastTemplateRequestDto(importDto));
        }
    }

    private List<ContrastTemplateImportExcelDto> getExcelData(String backUpFilePath) {
        ExcelImportResult<ContrastTemplateImportExcelDto> convertAfterList = readExcel(backUpFilePath);
//        if (CollectionUtil.isNotEmpty(convertAfterList.getFailList())) {
//            StringBuffer sb = new StringBuffer();
//            for (ContrastTemplateExcelDto p : convertAfterList.getFailList()) {
//                sb.append("第" + (p.getRowNum() + 1) + "行的错误是：\n" + p.getErrorMsg().replaceAll(",", "\n")).append("\n");
//            }
//            throw new RuntimeException(sb.toString());
//        }
        return convertAfterList.getList();
    }

    private ExcelImportResult<ContrastTemplateImportExcelDto> readExcel(String backUpFilePath) {
        ImportParams importParams = new ImportParams();
        importParams.setStartRows(1);
//        importParams.setNeedVerify(false);//开启校验
        return ExcelImportUtil.importExcelMore(new File(backUpFilePath), ContrastTemplateImportExcelDto.class, importParams);
    }

    private String backupUploadFile(MultipartFile multipartFile) {
        String backUpPath = org.apache.commons.io.FilenameUtils.separatorsToSystem(filePath + File.separator + "static/uploadFile/contrastTemplate");
        com.hex.bigdata.hbda.utils.FileUtil.mkdir(backUpPath);
        String updateFilePath = org.apache.commons.io.FilenameUtils.separatorsToSystem(backUpPath + File.separator);
        File file = upload(multipartFile, updateFilePath);
        log.debug("上传到服务器的EXCEL文件路径: {}", file.getPath());
        return file.getPath();
    }

    private String createSavePath() {
        String savePath = filePath + File.separator + "static/downExcel/contrastTemplate" + File.separator + cn.hutool.core.date.DateUtil.today() + File.separator + DateUtil.current(false);
        FileUtil.mkdir(savePath);
        return FilenameUtils.separatorsToSystem(savePath);
    }

    public List<CrossDbContrastTemplatePo> selectAll(){
        return crossDbContrastTemplateRepository.queryList(new CrossDbContrastTemplatePo());
    }
    /*
     * @param excelData:
     * @return List<String>
     * @author Liang Fuhao
     * @description 返回校验的错误信息
     * @date 2024/1/19 11:39
     */
    public List<String> verifyData(List<ContrastTemplateImportExcelDto> excelData){
        List<String> templateTask = this.selectAll().
                stream()
                .map(CrossDbContrastTemplatePo::getName)
                .collect(Collectors.toList());
        List<String> errorTemplateNames = excelData.stream()
                .filter(importDto -> templateTask.contains(importDto.getName()) || StrUtil.isEmpty(importDto.getName()))
                .map(ContrastTemplateImportExcelDto::getName)
                .collect(Collectors.toList());
        log.warn("本次导入的模板名{}导入失败（模板名称重复或为空）",errorTemplateNames);
        return errorTemplateNames;
    }
}
